package servlets;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.ImageIO;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;

import model.Errors;
import model.MultipartParameter;
import bean.BiedingBean;
import bean.GebruikerBean;
import bean.VeilingBean;
import exceptions.GebruikerBestaatNietException;
import exceptions.VeilingBestaatNietException;
/**
 * Servlet implementation class VeilingServlet
 */
public class VeilingServlet extends BasisServlet
{
	private static final long serialVersionUID = 1L;

	/**
	 * @throws IOException
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */

	private ArrayList<MultipartParameter> multiPartParameters = new ArrayList<MultipartParameter>();
	private String pathToImages;

	public void init(ServletConfig servletconfig)
	{
		super.init(servletconfig);
		pathToImages = getServletContext().getRealPath("/") + "images/veiling/";
		new File(pathToImages).mkdirs();
	}

	/**
	 * Hulp methode om plaatjes te verwijderen die bij een veiling horen
	 * 
	 * @param veilingid
	 */

	private void removePlaatjes(int veilingid)
	{
		new File(pathToImages + veilingid + "_orig.png").delete();
		new File(pathToImages + veilingid + ".png").delete();
		new File(pathToImages + veilingid + "_thumb.png").delete();
	}
	private BufferedImage resizeImage(BufferedImage original, boolean crop, int dH, int dW)
	{
		int originalHeight = original.getHeight(null);
		int originalWidth = original.getWidth(null);
		int desiredHeight = dH;
		int desiredWidth = dW;

		if (originalHeight > originalWidth)
		{
			desiredHeight = (int) (((double) desiredWidth / (double) originalWidth) * originalHeight);
		} else
		{
			desiredWidth = (int) (((double) desiredHeight / (double) originalHeight) * originalWidth);
		}

		BufferedImage resizedImage = null;
		if (crop)
			resizedImage = new BufferedImage(dW, dH, BufferedImage.TYPE_3BYTE_BGR);
		else
			resizedImage = new BufferedImage(desiredWidth, desiredHeight, BufferedImage.TYPE_3BYTE_BGR);
		Graphics2D g = (Graphics2D) resizedImage.getGraphics();
		g.drawImage(original, 0, 0, desiredWidth, desiredHeight, null);
		g.dispose();

		return resizedImage;
	}
	private void handleImage(MultipartParameter image, int id)
	{

		try
		{
			// plaatje in byte array zetten
			byte[] byteData = image.getData().getBytes("ISO-8859-1");

			// plaatje in van byte array bufferedimage laden
			InputStream is = new ByteArrayInputStream(byteData);
			BufferedImage imagein = null;
			imagein = ImageIO.read(is);
			is.close();

			// plaatje verkleinen/vergroten
			BufferedImage img = resizeImage(imagein, false, 550, 774);

			BufferedImage thumb = resizeImage(imagein, true, 100, 100);

			// plaatjes oplsaan in folder aangegeven in web.xml (documents)
			// %home% betekent de home folder

			ImageIO.write(imagein, "png", new File(pathToImages + id + "_orig.png"));
			ImageIO.write(img, "png", new File(pathToImages + id + ".png"));
			ImageIO.write(thumb, "png", new File(pathToImages + id + "_thumb.png"));

		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
		} catch (IOException e)
		{
			e.printStackTrace();
		}

	}
	private void parseMultiPartRequest(HttpServletRequest request) throws IOException
	{
		multiPartParameters.clear();
		String contentType = request.getContentType();

		if ((contentType != null) && (contentType.indexOf("multipart/form-data") >= 0))
		{
			DataInputStream in = new DataInputStream(request.getInputStream());
			int formDataLength = request.getContentLength();
			byte dataBytes[] = new byte[formDataLength];
			int byteRead = 0;
			int totalBytesRead = 0;

			while (totalBytesRead < formDataLength)
			{
				byteRead = in.read(dataBytes, totalBytesRead, formDataLength);
				totalBytesRead += byteRead;
			}

			String file = new String(dataBytes, "ISO-8859-1");
			String[] parts = file.split("------");

			Pattern namePattern = Pattern.compile(" name=\"[^\"]*\"");

			for (String part : parts)
			{
				Matcher m = namePattern.matcher(part);
				while (m.find())
				{
					String s = m.group();
					int dataStart = m.end();

					// name is resultaat van regex minus name=""
					String name = s.substring(7, s.length() - 1);

					// data is alles erachter minus /r/n
					String data = part.substring(dataStart + 4, part.length() - 2);

					// als Content-Type: dan is het een bestand
					// moeten we nog wat meer overslaan + filename laden
					String filename = null;

					if (part.contains("Content-Type:"))
					{
						Pattern filenamePattern = Pattern.compile("filename=\"[^\"]*\"");
						Matcher m2 = filenamePattern.matcher(part);
						if (m2.find())
						{
							String s2 = m2.group();
							filename = s2.substring(10, s2.length() - 1);
						}
						Pattern filePattern = Pattern.compile("\\r\\n\\r\\n");
						Matcher m3 = filePattern.matcher(data);
						if (m3.find())
						{
							data = data.substring(m3.end());
						}
					}

					MultipartParameter mPart = new MultipartParameter(name, data);
					if (filename != null)
						mPart.setFilename(filename);
					multiPartParameters.add(mPart);

				}
			}
		}
	}
	private MultipartParameter getMultiPartParameterData(String name)
	{
		for (MultipartParameter part : multiPartParameters)
		{
			if (part.getName().equals(name))
			{
				return part;
			}
		}
		return null;
	}

	private synchronized void removeVeiling(HttpServletRequest request, HttpServletResponse response, HttpSession session)
	{
		GebruikerBean gebruiker = null;
		VeilingBean veiling = null;
		try
		{
			gebruiker = gDao.getGebruiker((String) session.getAttribute("mail"));
			try
			{
				veiling = vDao.getVeiling(Integer.parseInt(request.getParameter("veiling")), bDao);
			} catch (NumberFormatException e)
			{
				melding(Errors.E005.getErorr(), request, response);
				return;
			} catch (VeilingBestaatNietException e)
			{
				melding(Errors.E009.getErorr(), request, response);
				return;
			}
			if (veiling.getGebruiker().getId() == gebruiker.getId())
			{
				vDao.delVeiling(veiling.getId());
				removePlaatjes(veiling.getId());
			}

		} catch (GebruikerBestaatNietException e)
		{
			melding(Errors.E007.getErorr(), request, response);
		}
		melding("Veiling is succesvol verwijderd", request, response);

	}

	private synchronized void addVeiling(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws IOException
	{
		if (!getMultiPartParameterData("title").getData().equals("")
				&& !getMultiPartParameterData("description").getData().equals("")
				&& !getMultiPartParameterData("days_valid").getData().equals("")
				&& !getMultiPartParameterData("minimum_bid").getData().equals(""))
		{
			try
			{
				String title = getMultiPartParameterData("title").getData();
				String description = getMultiPartParameterData("description").getData();
				int days_valid = Integer.parseInt(getMultiPartParameterData("days_valid").getData());
				int minimum_bid = Integer.parseInt(getMultiPartParameterData("minimum_bid").getData());

				if (days_valid > 0 && days_valid < 30 && minimum_bid > 0)
				{
					Calendar dateStart = Calendar.getInstance();
					Calendar dateEnd = Calendar.getInstance();
					GebruikerBean gebruiker = null;
					try
					{
						dateEnd.add(Calendar.DAY_OF_MONTH, days_valid);
						gebruiker = gDao.getGebruiker((String) session.getAttribute("mail"));

						vDao.addVeiling(gebruiker, dateStart, dateEnd, title, description, minimum_bid);
						VeilingBean veiling = vDao.getLastVeiling();
						MultipartParameter picture = getMultiPartParameterData("picture");
						handleImage(picture, veiling.getId());

						response.sendRedirect("index.html");

					} catch (GebruikerBestaatNietException e)
					{
						melding(Errors.E002.getErorr(), request, response);
						return;
					} catch (VeilingBestaatNietException e)
					{
						melding(Errors.E002.getErorr(), request, response);
						return;
					}
				} else
				{
					melding(Errors.E005.getErorr(), request, response);
					return;
				}
			} catch (NumberFormatException e)
			{
				melding(Errors.E005.getErorr(), request, response);
				return;
			}
		} else
		{
			melding(Errors.E001.getErorr(), request, response);
		}
	}

	private synchronized void getBiedingen(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws ServletException, IOException
	{
		try
		{
			int vid = Integer.parseInt(request.getParameter("veiling"));
			VeilingBean veiling = null;
			ArrayList<BiedingBean> biedingen = null;
			try
			{
				veiling = vDao.getVeiling(vid, bDao);
				biedingen = bDao.getBiedingen(veiling);
			} catch (VeilingBestaatNietException e)
			{
				melding(Errors.E009.getErorr(), request, response);
				return;
			}
			request.setAttribute("biedingen", biedingen);
			RequestDispatcher view = request.getRequestDispatcher("include/biedinglist.jsp");
			view.forward(request, response);
		} catch (NumberFormatException e)
		{
			System.out.println("Fout @GetBiedingen" + " veiling =" + Integer.parseInt(request.getParameter("veiling")));
			melding(Errors.E009.getErorr(), request, response);
		}
	}

	private synchronized void getVeiling(HttpServletRequest request, HttpServletResponse response, HttpSession session,
			String forward) throws ServletException, IOException
	{
		try
		{
			int vid = Integer.parseInt(request.getParameter("veiling"));

			VeilingBean veiling = null;
			try
			{
				veiling = vDao.getVeiling(vid, bDao);
			} catch (VeilingBestaatNietException e)
			{
				System.out.println("Veiling met id" + vid + " bestaat niet");
				melding(Errors.E009.getErorr(), request, response);
				return;
			}
			request.setAttribute("item", veiling);
			RequestDispatcher view = request.getRequestDispatcher(forward);
			view.forward(request, response);
		} catch (NumberFormatException e)
		{
			melding(Errors.E009.getErorr(), request, response);
		}
	}

	private synchronized void getGebruiker(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws ServletException, IOException
	{
		try
		{
			int gid = Integer.parseInt(request.getParameter("gebruiker"));
			GebruikerBean gebruiker = gDao.getGebruikerId(gid);

			request.setAttribute("gebruiker", gebruiker);
			request.setAttribute("veilinglijst", "getveilingen&gebruiker=" + gebruiker.getId());
			RequestDispatcher view = request.getRequestDispatcher("index.jsp");
			view.forward(request, response);
		} catch (GebruikerBestaatNietException e)
		{
			melding(Errors.E002.getErorr(), request, response);
		} catch (NumberFormatException e)
		{
			melding(Errors.E007.getErorr(), request, response);
		}
	}

	private synchronized void bekijkGebruikerVeilingen(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws ServletException, IOException
	{
		try
		{
			int gid = Integer.parseInt(request.getParameter("gebruiker"));
			GebruikerBean gebruiker = gDao.getGebruikerId(gid);
			ArrayList<VeilingBean> veilingen = vDao.getVeilingGebruiker(gebruiker, bDao);

			request.setAttribute("items", veilingen);
			RequestDispatcher view = request.getRequestDispatcher("include/itemlist.jsp");
			view.forward(request, response);
		} catch (GebruikerBestaatNietException e)
		{
			melding(Errors.E002.getErorr(), request, response);
		} catch (NumberFormatException e)
		{
			melding(Errors.E007.getErorr(), request, response);
		}
		
	}

	protected synchronized void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
		String action = request.getParameter("action");
		login(request);
		HttpSession session = request.getSession();

		request.setAttribute("imagepath", pathToImages);

		if (action != null)
		{
			// haal alle veilingen op
			if (action.equals("all"))
			{
				request.setAttribute("veilinglijst", "getalleveilingen");
				RequestDispatcher view = request.getRequestDispatcher("index.jsp");
				view.forward(request, response);
				return;
				// haal biedingen op van een bepaalde veiling voor AJAX
			} else if (action.equals("getbiedingen") && request.getParameter("veiling") != null)
			{
				getBiedingen(request, response, session);
				return;
				// haal alle veiling op voor AJAX request
			} else if (action.equals("getalleveilingen"))
			{
				request.setAttribute("items", vDao.getAlleVeilingen(100, bDao));
				RequestDispatcher view = request.getRequestDispatcher("include/itemlist.jsp");
				view.forward(request, response);
				return;
				// haal alle veilingen die binnen 7 dagen sluiten
				// en nog niet zijn gesloten
			} else if (action.equals("getveilingen"))
			{
				request.setAttribute("items", vDao.getVeilingen(100, bDao));
				RequestDispatcher view = request.getRequestDispatcher("include/itemlist.jsp");
				view.forward(request, response);
				return;
				// verwijder een veiling
			} else if (action.equals("remove") && request.getParameter("veiling") != null)
			{
				removeVeiling(request, response, session);
				return;

			} else if (action.equals("detail") && request.getParameter("gebruiker") != null)
			{
				getGebruiker(request, response, session);
				return;
				// haal alle veilingen van een gebruiker op voor AJAX request
			} else if (action.equals("kijkveilingen") && request.getParameter("gebruiker") != null)
			{
				bekijkGebruikerVeilingen(request, response, session);
				return;
			} else if (action.equals("veilinginfo") && request.getParameter("veiling") != null)
			{
				getVeiling(request, response, session, "include/veilinginfo.jsp");
				return;
			} else if (action.equals("kijkveiling") && request.getParameter("veiling") != null)
			{
				getVeiling(request, response, session, "veiling.jsp");
				return;
			} else if (action.equals("add"))
			{
				RequestDispatcher view = request.getRequestDispatcher("maakveiling.jsp");
				view.forward(request, response);
				return;
			} else
			{
				melding(Errors.E006.getErorr(), request, response);
				return;
			}
		} else
		{
			request.setAttribute("veilinglijst", "getveilingen");
			RequestDispatcher view = request.getRequestDispatcher("index.jsp");
			view.forward(request, response);
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
			IOException
	{
		parseMultiPartRequest(request);

		login(request);
		HttpSession session = request.getSession();

		String action = request.getParameter("action");
		if (action != null)
		{
			if (action.equals("add"))
			{
				addVeiling(request, response, session);
			}
		}
	}
}
